﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Globalization;
using System.Collections.ObjectModel;


namespace NobleTech.Products.CreatureKingdom.WPFClient.Controls
{
    
    public class Map : ListBox
    {
        private ScaleTransform CanvasScaleTransform = new ScaleTransform();
        private TranslateTransform CanvasTranslateTransform = new TranslateTransform();
        private double MousePositionX, MousePositionY;
        private bool IsMouseDown = false;

        public bool DisplayGrid
        {
            get { return (bool)GetValue(DisplayGridProperty); }
            set { SetValue(DisplayGridProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayGrid.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayGridProperty =
            DependencyProperty.Register("DisplayGrid", typeof(bool), typeof(Map), new UIPropertyMetadata(true));
        

        public double MapPositionX
        {
            get { return (double)GetValue(MapPositionXProperty); }
            set { SetValue(MapPositionXProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MapPositionX.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MapPositionXProperty =
            DependencyProperty.Register("MapPositionX", typeof(double), typeof(Map), new UIPropertyMetadata(0d));


        public double MapPositionY
        {
            get { return (double)GetValue(MapPositionYProperty); }
            set { SetValue(MapPositionYProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MapPositionY.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MapPositionYProperty =
            DependencyProperty.Register("MapPositionY", typeof(double), typeof(Map), new UIPropertyMetadata(0d));

        public double MapZoom
        {
            get { return (double)GetValue(MapZoomProperty); }
            set { SetValue(MapZoomProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MapZoom.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MapZoomProperty =
            DependencyProperty.Register("MapZoom", typeof(double), typeof(Map), new UIPropertyMetadata(1d, new PropertyChangedCallback(MapZoomChanged)));

        public static void MapZoomChanged (DependencyObject Sender, DependencyPropertyChangedEventArgs Args)
        {
            Map SenderMap = Sender as Map;
            if(SenderMap!=null)
                SenderMap.VerifyMapPosition();            
        }


        public double MapSizeX
        {
            get { return (double)GetValue(MapSizeXProperty); }
            set { SetValue(MapSizeXProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MapSizeX.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MapSizeXProperty =
            DependencyProperty.Register("MapSizeX", typeof(double), typeof(Map), new UIPropertyMetadata(10000d));


        public double MapSizeY
        {
            get { return (double)GetValue(MapSizeYProperty); }
            set { SetValue(MapSizeYProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MapSizeY.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MapSizeYProperty =
            DependencyProperty.Register("MapSizeY", typeof(double), typeof(Map), new UIPropertyMetadata(10000d));




        static Map()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Map), new FrameworkPropertyMetadata(typeof(Map)));            
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            
            base.MouseDown += new MouseButtonEventHandler(MouseDown);
            base.MouseUp += new MouseButtonEventHandler(MouseUp);
            base.MouseMove += new MouseEventHandler(MouseMove);
            base.SizeChanged += new SizeChangedEventHandler(Map_SizeChanged);
        }

        void Map_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            VerifyMapPosition();
        }
        
        private void MouseDown(object sender, MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            IsMouseDown = true;
            MousePositionX = e.GetPosition(this).X;
            MousePositionY = e.GetPosition(this).Y;
            Mouse.SetCursor(Cursors.Hand);
            Mouse.Capture(this, CaptureMode.Element);
            
        }

        private void MouseUp(object sender, MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            IsMouseDown = false;
            Mouse.SetCursor(Cursors.Arrow);
            Mouse.Capture(this, CaptureMode.None);            
         }

        private void MouseMove(object sender, MouseEventArgs e)
        {
            base.OnMouseMove(e);
            if (IsMouseDown)
            {
                MapPositionX -= (e.GetPosition(this).X - MousePositionX) / MapZoom;
                MapPositionY -= (e.GetPosition(this).Y - MousePositionY) / MapZoom;
                MousePositionX = e.GetPosition(this).X;
                MousePositionY = e.GetPosition(this).Y;
                VerifyMapPosition();
            }
        }

        private void VerifyMapPosition()
        {
            if (MapPositionX < (this.ActualWidth / 2 / MapZoom))
                MapPositionX = this.ActualWidth / 2 / MapZoom;
            if (MapPositionY < (this.ActualHeight / 2 / MapZoom))
                MapPositionY = this.ActualHeight / 2 / MapZoom;
            if (MapPositionX > MapSizeX - (this.ActualWidth / 2 / MapZoom))
                MapPositionX = MapSizeX - (this.ActualWidth / 2 / MapZoom);
            if (MapPositionY > MapSizeY - (this.ActualHeight / 2 / MapZoom))
                MapPositionY = MapSizeY - (this.ActualHeight / 2 / MapZoom);
            
        }
    }
}
